package com.timebank.volunteer.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.timebank.common.core.web.pojo.AjaxResult;
import com.timebank.volunteer.pojo.entity.*;
import com.timebank.volunteer.properties.GaoDeProperty;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Component
@Slf4j
public class GaoDeMapUtil {

    @Resource
    private GaoDeProperty gaoDeProperty;

    /**
     * 高德api 根据地址获取经纬度
     *
     * @param address
     * @return
     */
    public GeocodeResponse getLocationByAddress(String address) {
        StringBuffer s = new StringBuffer();
        s.append("key=" + gaoDeProperty.getKey() + "&address=" + address);
        String res = sendGet("http://restapi.amap.com/v3/geocode/geo", s.toString());
        log.info(res);
        //解析高德地图地理编码响应结果
        GeocodeResponse result = getGeocodeResponse(res);
        return result;
    }

    /**
     * 高德api 根据经纬度获取地址
     * @param longitude
     * @param latitude
     * @return
     */
    public ReGeocodeResponse getAddressByLocation(String longitude , String latitude) {
        String location = longitude + "," + latitude;
        StringBuffer s = new StringBuffer();
        s.append("key=")
                .append(gaoDeProperty.getKey())
                .append("&location=")
                .append(longitude)
                .append(",")
                .append(latitude);
        String res = sendGet("http://restapi.amap.com/v3/geocode/regeo", s.toString());
        log.info(res);
        //解析高德地图 逆地理编码 响应结果
        ReGeocodeResponse result = getReGeocodeResponse(location,res);
        return result;
    }

    /**
     * 计算两个经纬度之间的距离
     * @param startLonLat
     * @param endLonLat
     * @return
     */
    public Long getDistance(String startLonLat, String endLonLat){
        StringBuffer s = new StringBuffer();
        s.append("key=")
                .append(gaoDeProperty.getKey())
                .append("&origins=")
                .append(startLonLat)
                .append("&destination=")
                .append(endLonLat);
        String res = sendGet("http://restapi.amap.com/v3/distance", s.toString());
        log.info(res);
        //返回起始地startAddr与目的地endAddr之间的距离，单位：米
        Long result = new Long(0);
        JSONObject jsonObject = new net.sf.json.JSONObject().fromObject(res);
        JSONArray jsonArray = jsonObject.getJSONArray("results");
        result = Long.parseLong(new JSONObject().fromObject(jsonArray.getString(0)).get("distance").toString());
        return result;
    }


    /**
     * 获取当前Ip的地理位置，XX省XX市。没有参数，默认发出请求的ip地址
     * @param ip
     * @return resultStr
     *
     */
    public AjaxResult getPositionByIp(String ip){
        StringBuffer s = new StringBuffer();
        s.append("key=")
                .append(gaoDeProperty.getKey())
                .append("&ip=")
                .append(ip);
        String res = sendGet("https://restapi.amap.com/v3/ip", s.toString());
        log.info(res);
        com.alibaba.fastjson2.JSONObject jsonObject =
                com.alibaba.fastjson2.JSON.parseObject(res);
        IpResponse result = IpResponse.builder()
                .status(jsonObject.getString("status"))
                .info(jsonObject.getString("info"))
                .infocode(jsonObject.getString("infocode"))
                .province(jsonObject.getString("province"))
                .city(jsonObject.getString("city"))
                .adcode(jsonObject.getString("adcode"))
                .rectangle(jsonObject.getString("rectangle"))
                .build();
        return AjaxResult.success(result);
    }

    /**
     *  解析高德地图 地理编码 响应结果
     * @param res
     * @return
     */
    private static GeocodeResponse getGeocodeResponse(String res) {
        com.alibaba.fastjson2.JSONObject jsonObject =
                com.alibaba.fastjson2.JSON.parseObject(res);
        GeocodeResponse result = GeocodeResponse.builder()
                .status(jsonObject.getString("status"))
                .info(jsonObject.getString("info"))
                .count(jsonObject.getString("count"))
                .build();
        com.alibaba.fastjson2.JSONArray jsonArray = jsonObject.getJSONArray("geocodes");
        Geocodes geocodes = new Geocodes();
        if (jsonArray != null && jsonArray.size() != 0) {
            com.alibaba.fastjson2.JSONObject jsonObject2 = (com.alibaba.fastjson2.JSONObject) jsonArray.get(0);
            geocodes.setCountry(jsonObject2.getString("country"));
            geocodes.setProvince(jsonObject2.getString("province"));
            geocodes.setCity(jsonObject2.getString("city"));
            geocodes.setCitycode(jsonObject2.getString("citycode"));
            geocodes.setDistrict(jsonObject2.getString("district"));
            geocodes.setTownship(jsonObject2.getString("township"));
            geocodes.setStreet(jsonObject2.getString("street"));
            geocodes.setNumber(jsonObject2.getString("number"));
            geocodes.setAdcode(jsonObject2.getString("adcode"));
            geocodes.setLocation(jsonObject2.getString("location"));
            geocodes.setLevel(jsonObject2.getString("level"));
            geocodes.setFormatted_address(jsonObject2
                    .getString("formatted_address"));
        }
        result.setGeocodes(geocodes);
        return result;
    }

    /**
     * 解析高德地图 逆地理编码 响应结果
     * @param location
     * @param res
     * @return
     */
    private ReGeocodeResponse getReGeocodeResponse(String location,String res) {
        com.alibaba.fastjson2.JSONObject jsonObject =
                com.alibaba.fastjson2.JSON.parseObject(res);
        ReGeocodeResponse result = ReGeocodeResponse.builder()
                .status(jsonObject.getString("status"))
                .info(jsonObject.getString("info"))
                .build();
        com.alibaba.fastjson2.JSONObject regeocode =
                jsonObject.getJSONObject("regeocode");
        com.alibaba.fastjson2.JSONObject  addressComponent =
                regeocode.getJSONObject("addressComponent");
        com.alibaba.fastjson2.JSONObject streetNumber =
                addressComponent.getJSONObject("streetNumber");
        ReGeocode reGeocode = ReGeocode.builder()
                .country(addressComponent.getString("country"))
                .province(addressComponent.getString("province"))
                .city(addressComponent.getString("city"))
                .citycode(addressComponent.getString("citycode"))
                .district(addressComponent.getString("district"))
                .adcode(addressComponent.getString("adcode"))
                .township(addressComponent.getString("township"))
                .towncode(addressComponent.getString("towncode"))
                .street(streetNumber.getString("street"))
                .number(streetNumber.getString("number"))
                .location(location)
                .formatted_address(regeocode.getString("formatted_address"))
                .build();
        result.setRegeocode(reGeocode);
        return result;
    }

    public String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urladdressString = url + "?" + param;
            URL realUrl = new URL(urladdressString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                log.info(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            log.info("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 address1=value1&address2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            log.info("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * GET请求数据
     *
     * @param get_url url地址
     * @param content key=value形式
     * @return 返回结果
     * @throws Exception
     */
    public String sendGetData(String get_url, String content) throws Exception {
        String result = "";
        URL getUrl = null;
        BufferedReader reader = null;
        String lines = "";
        HttpURLConnection connection = null;
        try {
            if (content != null && !content.equals(""))
                get_url = get_url + "?" + content;
            // get_url = get_url + "?" + URLEncoder.encode(content, "utf-8");
            getUrl = new URL(get_url);
            connection = (HttpURLConnection) getUrl.openConnection();
            connection.connect();
            // 取得输入流，并使用Reader读取
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));// 设置编码
            while ((lines = reader.readLine()) != null) {
                result = result + lines;
            }
            return result;
        } catch (Exception e) {
            throw e;
        } finally {
            if (reader != null) {
                reader.close();
                reader = null;
            }
            connection.disconnect();
        }
    }

    /**
     * @param POST_URL url地址
     * @param content  key=value形式
     * @return 返回结果
     * @throws Exception
     */
    public String sendPostData(String POST_URL, String content) throws Exception {
        HttpURLConnection connection = null;
        DataOutputStream out = null;
        BufferedReader reader = null;
        String line = "";
        String result = "";
        try {
            URL postUrl = new URL(POST_URL);
            connection = (HttpURLConnection) postUrl.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            // Post 请求不能使用缓存
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.connect();

            out = new DataOutputStream(connection.getOutputStream());
            // content = URLEncoder.encode(content, "utf-8");
            // DataOutputStream.writeBytes将字符串中的16位的unicode字符�?8位的字符形式写道流里�?
            out.writeBytes(content);
            out.flush();
            out.close();
            // 获取结果
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));// 设置编码
            while ((line = reader.readLine()) != null) {
                result = result + line;
            }
            return result;
        } catch (Exception e) {
            throw e;
        } finally {
            if (out != null) {
                out.close();
                out = null;
            }
            if (reader != null) {
                reader.close();
                reader = null;
            }
            connection.disconnect();
        }
    }

    /**
     * 过滤掉html里不安全的标签，不允许用户输入这些标签
     * @param inputString
     * @return
     */
    public String htmlFilter(String inputString) {
        // return inputString;
        String htmlStr = inputString; // 含html标签的字符串
        String textStr = "";
        java.util.regex.Pattern p_script;
        java.util.regex.Matcher m_script;

        try {
            String regEx_script = "<[\\s]*?(script|style)[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?(script|style)[\\s]*?>";
            String regEx_onevent = "on[^\\s]+=\\s*";
            String regEx_hrefjs = "href=javascript:";
            String regEx_iframe = "<[\\s]*?(iframe|frameset)[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?(iframe|frameset)" +
                    "[\\s]*?>";
            String regEx_link = "<[\\s]*?link[^>]*?/>";

            htmlStr = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE).matcher(htmlStr).replaceAll("");
            htmlStr = Pattern.compile(regEx_onevent, Pattern.CASE_INSENSITIVE).matcher(htmlStr).replaceAll("");
            htmlStr = Pattern.compile(regEx_hrefjs, Pattern.CASE_INSENSITIVE).matcher(htmlStr).replaceAll("");
            htmlStr = Pattern.compile(regEx_iframe, Pattern.CASE_INSENSITIVE).matcher(htmlStr).replaceAll("");
            htmlStr = Pattern.compile(regEx_link, Pattern.CASE_INSENSITIVE).matcher(htmlStr).replaceAll("");

            textStr = htmlStr;

        } catch (Exception e) {
            System.err.println("Html2Text: " + e.getMessage());
        }

        return textStr;
    }
}